﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using Update.Utils.Core;
using Downloader;

namespace Update.Servers.LanZou {
    /// <summary>
    /// 蓝奏网盘服务器实现
    /// </summary>
    public class LanZouServer : Update.IUpdateServer {

        private WebClient webClient = new WebClient();
        private LanZouApi lanZouApi = new LanZouApi();
        private string serverUrl;
        private string filePwd;
        private Dictionary<string, LanZouApi.LanZouFile> versionCache = new Dictionary<string, LanZouApi.LanZouFile>();
        private Dictionary<string, string> changelogCache = new Dictionary<string, string>();
        private bool enableChangelog = false;
        private string versionFilePattern = @"(.+)(\d+\.\d+\.\d+)\.zip"; // 默认文件名格式

        /// <summary>
        /// 是否支持更新日志功能
        /// </summary>
        public bool SupportsChangelog => enableChangelog;

        /// <summary>
        /// 检查是否有更新
        /// </summary>
        /// <param name="version">当前版本</param>
        /// <returns>是否有更新</returns>
        public async Task<bool> CheckUpdateAsync(string version) {
            try {
                string latestVersion = await GetLatestVersionAsync();
                if (string.IsNullOrEmpty(latestVersion))
                    return false;

                // 使用VersionHelper比较版本号
                return VersionHelper.IsNewerVersion(latestVersion, version);
            } catch {
                return false;
            }
        }

        /// <summary>
        /// 获取最新版本号
        /// </summary>
        public async Task<string> GetLatestVersionAsync() {
            try {
                // 如果缓存为空，重新加载版本列表
                if (versionCache.Count == 0) {
                    var latestFile = await lanZouApi.GetLatestFileAsync(serverUrl, filePwd);
                    if (latestFile != null) {
                        // 使用VersionHelper从文件名提取版本号
                        string version = VersionHelper.ExtractVersionFromFilename(latestFile.FileName, versionFilePattern);
                        if (!string.IsNullOrEmpty(version)) {
                            versionCache[version] = latestFile;
                            return version;
                        }
                    }
                    return string.Empty;
                } else {
                    // 从缓存中找出最高版本
                    if (versionCache.Count > 0) {
                        string maxVersion = null;
                        foreach (var version in versionCache.Keys) {
                            if (maxVersion == null || VersionHelper.IsNewerVersion(version, maxVersion)) {
                                maxVersion = version;
                            }
                        }
                        return maxVersion;
                    }
                    return string.Empty;
                }
            } catch (Exception ex) {
                Console.WriteLine($"获取最新版本失败: {ex.Message}");
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取服务器版本
        /// </summary>
        /// <returns>服务器版本号</returns>
        public string GetServerVersion() {
            try {
                // 使用Task.Run隔离同步上下文，避免死锁
                var task = Task.Run(async () => {
                    return await GetLatestVersionAsync().ConfigureAwait(false);
                });

                // 等待任务完成
                task.Wait();
                return task.Result;
            } catch (Exception ex) {
                // 提取内部异常
                if (ex is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0) {
                    throw new Exception($"获取网盘服务器版本失败: {aggregateException.InnerExceptions[0].Message}");
                }
                throw new Exception($"获取网盘服务器版本失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 下载更新包
        /// </summary>
        /// <param name="version">版本号</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="progressCallback">进度回调</param>
        /// <returns>下载的文件路径</returns>
        public string DownloadUpdatePackage(string version, string savePath, Action<int, double, string> progressCallback) {
            try {
                // 确定更新包保存路径
                string updatePackagePath = Path.Combine(savePath, $"app-{version}.zip");

                // 使用异步转同步的安全方式
                var task = Task.Run(async () => {
                    // 检查版本缓存中是否有该版本的文件信息
                    if (versionCache.TryGetValue(version, out var file)) {
                        // 从缓存中获取文件ID，然后获取下载链接
                        progressCallback?.Invoke(0,0, $"正在获取文件下载链接...");

                        // 使用异步方法获取下载链接，但避免使用.Wait()
                        string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(file.FileId)
                            .ConfigureAwait(false);

                        if (string.IsNullOrEmpty(downloadUrl)) {
                            throw new Exception("无法获取文件下载链接");
                        }

                        progressCallback?.Invoke(0, 0, $"正在从网盘下载更新包...");

                        // 创建下载配置
                        var downloadConfig = new DownloadConfiguration {
                            BufferBlockSize = 10240, // 缓冲区大小
                            ChunkCount = 8,          // 分块数
                            MaximumBytesPerSecond = 0, // 不限制下载速度
                            MaxTryAgainOnFailover = 5, // 失败重试次数
                            ParallelDownload = true, // 启用并行下载
                            Timeout = 5000,          // 超时时间
                            RequestConfiguration = {
                                Accept = "*/*",
                                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                                UseDefaultCredentials = false,
                                KeepAlive = false
                            }
                        };

                        // 创建下载服务
                        var downloader = new DownloadService(downloadConfig);

                        try {
                            // 进度事件（含速度）  
                            downloader.DownloadProgressChanged += (s, e) => {
                                Console.WriteLine($"进度: {(int)e.ProgressPercentage}%, 速度: {e.BytesPerSecondSpeed / 1024} KB/s");
                                progressCallback?.Invoke((int)e.ProgressPercentage, e.BytesPerSecondSpeed, $"下载更新包: {e.ProgressPercentage}%");
                            };
                            // 下载完成事件
                            downloader.DownloadFileCompleted += (s, e) => {
                                try {
                                    if (e.Cancelled) {
                                        Console.WriteLine("下载已取消");
                                    } else if (e.Error != null) {
                                        Console.WriteLine($"下载失败: {e.Error.Message}");
                                    } else {
                                        progressCallback?.Invoke(100,0, $"下载更新包: 100%");
                                    }
                                } catch (Exception ex) {
                                    Console.WriteLine($"处理下载完成事件时出错: {ex.Message}");
                                }
                            };

                            await downloader.DownloadFileTaskAsync(downloadUrl, updatePackagePath);

                            return updatePackagePath;
                        } finally {
                            // 确保释放下载器资源
                            downloader.Dispose();
                        }
                    } else {
                        // 如果缓存中没有，尝试获取最新文件
                        progressCallback?.Invoke(20,0, "缓存中没有对应版本，尝试获取最新文件...");

                        // 获取文件列表，使用ConfigureAwait(false)避免死锁
                        var files = await lanZouApi.GetFileListAsync(serverUrl, filePwd, true)
                            .ConfigureAwait(false);

                        // 查找匹配的文件
                        LanZouApi.LanZouFile matchFile = null;
                        foreach (var f in files) {
                            // 使用VersionHelper检查文件名中的版本
                            string fileVersion = VersionHelper.ExtractVersionFromFilename(f.FileName, versionFilePattern);
                            if (!string.IsNullOrEmpty(fileVersion) && fileVersion == version) {
                                matchFile = f;
                                break;
                            }
                        }

                        if (matchFile == null) {
                            throw new Exception($"找不到版本为 {version} 的更新包");
                        }

                        // 获取下载链接
                        progressCallback?.Invoke(35, 0, "正在获取文件下载链接...");
                        string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(matchFile.FileId)
                            .ConfigureAwait(false);

                        if (string.IsNullOrEmpty(downloadUrl)) {
                            throw new Exception("无法获取文件下载链接");
                        }

                        progressCallback?.Invoke(40, 0, "正在从网盘下载更新包...");

                        // 创建新的WebClient实例，避免重用可能导致的问题
                        using (var downloader = new WebClient()) {
                            // 设置下载进度事件
                            downloader.DownloadProgressChanged += (s, e) => {
                                progressCallback?.Invoke(40 + e.ProgressPercentage / 2, 0, $"下载更新包: {e.ProgressPercentage}%");
                            };

                            // 下载文件
                            downloader.DownloadFile(new Uri(downloadUrl), updatePackagePath);
                        }

                        return updatePackagePath;
                    }
                });

                // 等待任务完成
                task.Wait(); // 这里使用Task.Run + Wait方式避免了SynchronizationContext带来的死锁

                progressCallback?.Invoke(95, 0, "更新包下载完成");

                return task.Result;
            } catch (Exception ex) {
                // 确保提取出内部异常
                if (ex is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0) {
                    throw new Exception($"从网盘下载更新包失败: {aggregateException.InnerExceptions[0].Message}");
                }
                throw new Exception($"从网盘下载更新包失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 下载更新包
        /// </summary>
        /// <param name="version">版本号</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="progressCallback">进度回调</param>
        /// <returns>下载的文件路径</returns>
        public string DownloadUpdatePackage_bak(string version, string savePath, Action<int, string> progressCallback) {
            try {
                // 确定更新包保存路径
                string updatePackagePath = Path.Combine(savePath, $"app-{version}.zip");

                // 使用异步转同步的安全方式
                var task = Task.Run(async () => {
                    // 检查版本缓存中是否有该版本的文件信息
                    if (versionCache.TryGetValue(version, out var file)) {
                        // 从缓存中获取文件ID，然后获取下载链接
                        progressCallback?.Invoke(35, $"正在获取文件下载链接...");

                        // 使用异步方法获取下载链接，但避免使用.Wait()
                        string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(file.FileId)
                            .ConfigureAwait(false);

                        if (string.IsNullOrEmpty(downloadUrl)) {
                            throw new Exception("无法获取文件下载链接");
                        }

                        progressCallback?.Invoke(40, $"正在从网盘下载更新包...");

                        // 创建新的WebClient实例，避免重用可能导致的问题
                        using (var downloader = new WebClient()) {
                            // 设置下载进度事件
                            downloader.DownloadProgressChanged += (s, e) => {
                                progressCallback?.Invoke(40 + e.ProgressPercentage / 2, $"下载更新包: {e.ProgressPercentage}%");
                            };

                            // 下载文件
                            downloader.DownloadFile(new Uri(downloadUrl), updatePackagePath);
                        }

                        return updatePackagePath;
                    } else {
                        // 如果缓存中没有，尝试获取最新文件
                        progressCallback?.Invoke(20, "缓存中没有对应版本，尝试获取最新文件...");

                        // 获取文件列表，使用ConfigureAwait(false)避免死锁
                        var files = await lanZouApi.GetFileListAsync(serverUrl, filePwd, true)
                            .ConfigureAwait(false);

                        // 查找匹配的文件
                        LanZouApi.LanZouFile matchFile = null;
                        foreach (var f in files) {
                            // 使用VersionHelper检查文件名中的版本
                            string fileVersion = VersionHelper.ExtractVersionFromFilename(f.FileName, versionFilePattern);
                            if (!string.IsNullOrEmpty(fileVersion) && fileVersion == version) {
                                matchFile = f;
                                break;
                            }
                        }

                        if (matchFile == null) {
                            throw new Exception($"找不到版本为 {version} 的更新包");
                        }

                        // 获取下载链接
                        progressCallback?.Invoke(35, "正在获取文件下载链接...");
                        string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(matchFile.FileId)
                            .ConfigureAwait(false);

                        if (string.IsNullOrEmpty(downloadUrl)) {
                            throw new Exception("无法获取文件下载链接");
                        }

                        progressCallback?.Invoke(40, "正在从网盘下载更新包...");

                        // 创建新的WebClient实例，避免重用可能导致的问题
                        using (var downloader = new WebClient()) {
                            // 设置下载进度事件
                            downloader.DownloadProgressChanged += (s, e) => {
                                progressCallback?.Invoke(40 + e.ProgressPercentage / 2, $"下载更新包: {e.ProgressPercentage}%");
                            };

                            // 下载文件
                            downloader.DownloadFile(new Uri(downloadUrl), updatePackagePath);
                        }

                        return updatePackagePath;
                    }
                });

                // 等待任务完成
                task.Wait(); // 这里使用Task.Run + Wait方式避免了SynchronizationContext带来的死锁

                progressCallback?.Invoke(95, "更新包下载完成");

                return task.Result;
            } catch (Exception ex) {
                // 确保提取出内部异常
                if (ex is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0) {
                    throw new Exception($"从网盘下载更新包失败: {aggregateException.InnerExceptions[0].Message}");
                }
                throw new Exception($"从网盘下载更新包失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 异步下载更新包
        /// </summary>
        /// <param name="version">版本号</param>
        /// <returns>文件流</returns>
        public async Task<Stream> DownloadUpdateAsync(string version) {
            try {
                // 如果指定了版本但缓存中不存在，重新获取版本列表
                if (!string.IsNullOrEmpty(version) && !versionCache.ContainsKey(version)) {
                    versionCache = await lanZouApi.GetVersionsAsync(serverUrl, filePwd);
                }

                // 如果指定了版本且缓存中有对应文件信息
                if (!string.IsNullOrEmpty(version) && versionCache.ContainsKey(version)) {
                    var file = versionCache[version];
                    var fileStream = new MemoryStream();

                    // 获取文件下载链接
                    string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(file.FileId);
                    if (string.IsNullOrEmpty(downloadUrl)) {
                        throw new Exception($"无法获取文件下载链接: {file.FileName}");
                    }

                    // 下载文件，使用新的WebClient实例
                    using (var downloader = new WebClient()) {
                        var data = await downloader.DownloadDataTaskAsync(new Uri(downloadUrl));
                        fileStream.Write(data, 0, data.Length);
                        fileStream.Position = 0;
                        return fileStream;
                    }
                }
                // 如果未指定版本或缓存中没有对应文件，获取最新版本
                else {
                    var latestFile = await lanZouApi.GetLatestFileAsync(serverUrl, filePwd);
                    if (latestFile != null) {
                        var fileStream = new MemoryStream();

                        // 获取文件下载链接
                        string downloadUrl = await lanZouApi.GetFileDownloadUrlAsync(latestFile.FileId);
                        if (string.IsNullOrEmpty(downloadUrl)) {
                            throw new Exception($"无法获取最新版本下载链接: {latestFile.FileName}");
                        }

                        // 下载文件，使用新的WebClient实例
                        using (var downloader = new WebClient()) {
                            var data = await downloader.DownloadDataTaskAsync(new Uri(downloadUrl));
                            fileStream.Write(data, 0, data.Length);
                            fileStream.Position = 0;
                            return fileStream;
                        }
                    }
                }

                return null;
            } catch (Exception ex) {
                Console.WriteLine($"下载更新失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取更新日志
        /// </summary>
        /// <param name="version">版本号</param>
        /// <returns>更新日志内容</returns>
        public string GetChangelog(string version) {
            try {
                // 检查是否启用了更新日志
                if (!enableChangelog)
                    return string.Empty;

                // 如果有缓存的更新日志，直接返回
                if (changelogCache.ContainsKey(version))
                    return changelogCache[version];

                // 使用Task.Run隔离同步上下文，避免死锁
                var task = Task.Run(async () => {
                    return await GetChangelogAsync(version).ConfigureAwait(false);
                });

                // 等待任务完成
                task.Wait();
                return task.Result;
            } catch (Exception ex) {
                // 提取内部异常
                if (ex is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0) {
                    Console.WriteLine($"获取更新日志失败: {aggregateException.InnerExceptions[0].Message}");
                } else {
                    Console.WriteLine($"获取更新日志失败: {ex.Message}");
                }
                return string.Empty;
            }
        }

        /// <summary>
        /// 异步获取更新日志
        /// </summary>
        /// <param name="version">版本号</param>
        /// <returns>更新日志内容</returns>
        public async Task<string> GetChangelogAsync(string version) {
            try {
                // 检查是否启用了更新日志
                if (!enableChangelog)
                    return string.Empty;

                // 如果有缓存的更新日志，直接返回
                if (changelogCache.ContainsKey(version))
                    return changelogCache[version];

                // 如果未指定版本或版本缓存为空，获取最新版本
                if (string.IsNullOrEmpty(version) || versionCache.Count == 0) {
                    var latestFile = await lanZouApi.GetLatestFileAsync(serverUrl, filePwd);
                    if (latestFile == null) return string.Empty;

                    // 提取版本号
                    var versionMatch = Regex.Match(latestFile.FileName, versionFilePattern);
                    if (!versionMatch.Success || versionMatch.Groups.Count <= 1) return string.Empty;

                    version = versionMatch.Groups[1].Value;

                    // 更新缓存
                    if (!versionCache.ContainsKey(version))
                        versionCache[version] = latestFile;
                }

                // 如果缓存中有对应的文件信息
                if (versionCache.ContainsKey(version)) {
                    var file = versionCache[version];
                    string changelog = await lanZouApi.GetChangelogAsync(file.FileId);

                    // 更新缓存
                    changelogCache[version] = changelog;

                    return changelog;
                }

                return string.Empty;
            } catch (Exception ex) {
                Console.WriteLine($"获取更新日志失败: {ex.Message}");
                return string.Empty;
            }
        }

        /// <summary>
        /// 初始化服务器
        /// </summary>
        /// <param name="config">配置信息</param>
        public void Initialize(XElement config) {
            if (config == null)
                throw new ArgumentNullException(nameof(config));

            // 获取蓝奏云分享链接
            serverUrl = config.Element("ServerUrl")?.Value;
            if (string.IsNullOrEmpty(serverUrl))
                throw new ArgumentException("未配置蓝奏云分享链接");

            // 获取分享密码
            filePwd = config.Element("FilePwd")?.Value;

            // 初始化蓝奏云API
            lanZouApi.SetBaseUrl(serverUrl);

            // 检查是否启用更新日志
            string enableChangelogStr = config.Element("EnableChangelog")?.Value;
            if (!string.IsNullOrEmpty(enableChangelogStr))
                bool.TryParse(enableChangelogStr, out enableChangelog);

            // 检查是否有自定义的文件名格式
            string customPattern = config.Element("VersionPattern")?.Value;
            if (!string.IsNullOrEmpty(customPattern))
                versionFilePattern = customPattern;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose() {
            try {
                // 释放WebClient资源
                webClient?.Dispose();

                // 清理字典和缓存
                versionCache?.Clear();
                changelogCache?.Clear();

                // 释放LanZouApi资源（如果它实现了IDisposable接口）
                if (lanZouApi is IDisposable disposableLanZouApi) {
                    disposableLanZouApi.Dispose();
                }

                // 清除大型对象
                versionCache = null;
                changelogCache = null;
                webClient = null;
                lanZouApi = null;
            } catch (Exception ex) {
                Console.WriteLine($"释放资源时发生错误: {ex.Message}");
            }
        }
    }
}